﻿'''
Author: Lucia Eder
Date: 16.04.2012

Modul, das Methoden zur Berechnung und Darstellung von Zustandsgroessen
eines Modells bereitstellt.
'''

from matplotlib.pylab import axis, xlabel, ylabel, title, plot, show, legend


class Sahel:
    
    
    def __init__(self, name, stock, growthrate, decreaserate,
                 units="Einheiten", capacity=0, influence=0.01, minPrecip=0,
                 maxPrecip=0, initialtime=0, finaltime=1, timestep=1, plots=1,
                 visualPlot=1): 
        '''
        Die Methode initialisiert alle Attribute und macht diese fuer alle
        Methoden der Klasse verfuegbar.
        
        Args:
            name:             Name der Zustandsgroesse
            stock:            Initialer Wert der Zustandsgroesse
            growthrate:       Konstante Zunahmerate
            decreaserate:     Konstante Abnahmerate
            initialtime:      Beginn der Simulation
            finaltime:        Ende der Simulation
            timerange:        Dauer der Simulation
            units:            Einheit der Zustandsgroesse
            capacity:         Kapazitaetsgrenze o. Normierungswert 
                              einer Einflussgroesse
            influence:        Einflussfaktor einer Zwischengroesse
            minPrecip:        Minimal benoetiger Niederschlag um Ertrag zu 
                              erzeugen
            maxPrecip:        Maximal erreichbarer Niederschlag    
            plots:            Anzahl der Untersuchungsflaechen
            visualPlot:       Nummer der Untersuchungsflaeche, die visualisiert
                              werden soll
        '''
        self.name = name
        self.stock = [stock]
        self.growthrate = growthrate
        self.decreaserate = decreaserate
        self.initialtime = [initialtime]
        self.finaltime = finaltime
        self.timestep = timestep
        self.timerange = self.finaltime - self.initialtime[0]
        self.units = units
        self.capacity = capacity
        self.influence = influence
        self.minPrecip = minPrecip
        self.maxPrecip = maxPrecip
        self.plots = plots
        self.visualPlot = visualPlot
    
    def growth(self):    
        '''
        Methode zur Berechnung der Zunahmerate innerhalb eines Zeitschrittes.
        
        Returns:
            Absoluter Zuwachs eines Stocks innerhalb eines Zeitschrittes
        '''
        return self.stock[len(self.stock) - 1] * self.growthrate * (
                self.timestep)
    
    def decrease (self):
        '''
        Methode zur Berechnung der Abnahmerate innerhalb eines Zeitschrittes.
        
        Returns:
            Absolute Abnahme eines Stocks innerhalb eines Zeitschrittes
        '''
        return self.stock[len(self.stock) - 1] * self.decreaserate * (
                self.timestep)

    def setStock(self):
        '''
        Berechnung der Zustandsgroesse zu einem Zeitpunkt aus der Differenz 
        seiner Veraenderungsraten.
        
        Returns:
            Wert des Stocks zu einem bestimmten Zeitpunkt
        '''
        stocknow = self.stock[len(self.stock) - 1] + self.growth() - (
                    self.decrease())
        timenow = self.initialtime[len(self.stock) - 1] + self.timestep
        self.stock.append(stocknow)
        self.initialtime.append(timenow)
        return self.stock[len(self.stock) - 1]
        
    def getStock (self):
        '''
        Methode, die den Wert einer Zustandsgroesse ausgibt.
        '''
        print "%s zum Zeitpunkt %s" % (self.name, 
                self.initialtime[len(self.initialtime) - 1])
        print self.stock[len(self.stock) - 1], self.units, "\n"
        
    def getAllStocks (self, j):
        '''
        Methode, die die zuletzt berechneten Werte aller drei Zustandsgroessen
        ausgibt.
        
        Args:
            j:    Die Zustandsgroessen des an j-ter Stelle berechneten 
                  Plots werden ausgegeben. 
        '''        
        i = j + 1
        print "Dynamik der Sahelzone an Plot %s" % i
        print "%s zum Zeitpunkt %s\n%s %s\n" % (self.name, 
                self.initialtime[len(self.initialtime) - 1],
                self.stock[len(self.stock) - 1], self.units)
        print "%s zum Zeitpunkt %s\n%s %s\n" % (self.prey.name, 
                self.initialtime[len(self.initialtime) - 1],
                self.prey.stock[len(self.prey.stock) - 1], self.prey.units)
        print "%s zum Zeitpunkt %s\n%s %s\n" % (self.pred.name, 
                self.initialtime[len(self.initialtime) - 1],
                self.pred.stock[len(self.pred.stock) - 1], self.pred.units)
    
    def setInitial (self):
        '''
        Methode, die die Listen der Stocks auf den ersten Wert (Anfangswert) 
        des jeweiligen Stocks reduziert.
        '''
        self.stock = [self.stock[0]]
        self.initialtime = [self.initialtime[0]]
        
    def setPred(self, pred):
        '''
        Diese Methode kann einer Konsumenteninstanz ihre Verbrauchsgrundlage in
        Form einer anderen Instanz zuweisen. Dadurch kann die eine Instanz 
        auf die Variablen der jeweils anderen zugreifen. 
        Funktion wird nur zur Visualisierung und Ausgabe verwendet.
        
        Args:
            pred:    Die Instanz, die den Stock der aufrufenden Instanz 
                     konsumiert bzw. reduziert.
        '''
        self.pred = pred
        
    def setPrey(self, prey):
        '''
        Diese Methode kann einer konsumierten Instanz ihre konsumierende 
        Instanz zuweisen. Dadurch kann die eine Instanz auf die Variablen der 
        jeweils anderen zugreifen. 
        Funktion wird nur zur Visualisierung und Ausgabe verwendet.
        
        Args:
            prey:    Die Instanz, dessen Stock von der die Methode aufrufenden
                     Instanz konsumiert bzw. reduziert wird.
        '''
        self.prey = prey
        
    def plotStock(self, env):
        '''
        Methode, die die Entwicklung von drei Stocks in einer Graphik 
        darstellt (mit Hilfe von matplotlib.pyplot). Dazu werden alle in die 
        Listen geschriebenen Werte geplottet ("r.": mit roten Punkten, 
        keine Linie). 
        Achsen sind von den Anfangs- und Endwerten der Zeit und Bevoelkerung 
        abhaengig.
        
        Args:
            env:    Sahel-Instanz, die die Umweltvariablen wie Zeitrahmen, 
                    Niederschlagscharakteristika u.a. bereitstellt
        '''
        x_series = self.initialtime
        y1_series = self.stock
        y2_series = self.prey.stock
        y3_series = self.pred.stock
        axis([env.initialtime[0], env.finaltime,
              (min(min(self.prey.stock), min(self.pred.stock), 
                   min(self.stock))),
              (max(max(self.prey.stock), max(self.pred.stock), 
                   max(self.stock)))
              ])
        plot(x_series, y1_series, "b", label=self.name)
        plot(x_series, y2_series, "r", label=self.prey.name)
        plot(x_series, y3_series, "g", label=self.pred.name)
        xlabel("Zeit")
        ylabel("%s [%s] - %s [%s]\n - %s [%s]" % (
                self.name, self.units, self.prey.name, self.prey.units,
                 self.pred.name, self.pred.units))
        title("Dynamik der Sahelzone in Plot Nr. %s von %s" % (
               env.visualPlot, env.plots))
        legend()
        show()